package com.lb.uts.util;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.text.ParseException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.temporal.ChronoUnit;
import java.util.Date;

public class TimeUtils {
    public static final String ISO_BASE_DATE = "yyyyMMdd";
    public static final String ISO_BASE_DATETIME = "yyyyMMddHHmmss";
    public static final String ISO_BASE_DATETIME_MILLI = "yyyyMMddHHmmssSSS";

    public static final String ISO_DASH_DATE = "yyyy-MM-dd";
    public static final String ISO_DASH_DATETIME= "yyyy-MM-dd HH:mm:ss";
    public static final String ISO_DASH_DATETIME_MILLI = "yyyy-MM-dd HH:mm:ss.SSS";

    public static final String ISO_SLASH_DATE = "yyyy/MM/dd";
    public static final String ISO_SLASH_DATETIME = "yyyy/MM/dd HH:mm:ss";
    public static final String ISO_SLASH_DATETIME_MILLI = "yyyy/MM/dd HH:mm:ss.SSS";


    private static final String[] patterns = new String[]{
            ISO_BASE_DATE, ISO_BASE_DATETIME, ISO_BASE_DATETIME_MILLI,
            ISO_DASH_DATE, ISO_DASH_DATETIME, ISO_DASH_DATETIME_MILLI,
            ISO_SLASH_DATE, ISO_SLASH_DATETIME, ISO_SLASH_DATETIME_MILLI
    };

    /**
     * 时间格式化
     * @param date
     * @param pattern
     * @return
     */
    public static String format(Date date, String pattern) {
        return DateFormatUtils.format(date, pattern);
    }

    /**
     * <p>按给定时间格式解析成时间对象</p>
     * 时间格式可以指定多个, 按顺序解析<br/>
     * 返回第一个可以解析成功的时间格式对应的时间<br/>
     * @param date
     * @param pattern 给定多个时间格式
     * @return
     */
    public static Date parse(String date, String... pattern) {
        try {
            return DateUtils.parseDateStrictly(date, pattern);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 用常用格式解析给定的时间字符串
     * @param date
     * @return
     */
    public static Date parse(String date) {
        return parse(date, patterns);
    }

    /**
     * 移动指定天数
     * @param sourceDate 起始日期
     * @param amount 移动天数, 正数向后移动, 负数向前移动
     * @return 增加后的日期
     */
    public static Date moveDays(Date sourceDate, int amount) {
        return DateUtils.addDays(sourceDate, amount);
    }

    /**
     * 取得两个日期之间相差的天数
     * @param startDate
     * @param endDate
     * @return
     */
    public static long getPeriodDays(Date startDate, Date endDate) {
        return getPeriod(startDate, endDate, ChronoUnit.DAYS);
    }

    /**
     * 取得两个日期之间相差的时间，时间单位根据 unit 值确认
     * @param startDate
     * @param endDate
     * @param unit 时间单位
     * @return
     */
    public static long getPeriod(Date startDate, Date endDate, ChronoUnit unit) {
        LocalDateTime start = TimeConvertUtils.convertToLocalDateTime(startDate);
        LocalDateTime end =  TimeConvertUtils.convertToLocalDateTime(endDate);
        return unit.between(start, end);
    }

    /**
     * 取得两个日期的时间段
     * @param startDate
     * @param endDate
     * @return 包含年月日信息的 Period, 两个日期相差 x 年 x 月 x 日
     */
    public static Period getPeriod(Date startDate, Date endDate) {
        LocalDate start = TimeConvertUtils.convertToLocalDate(startDate);
        LocalDate end = TimeConvertUtils.convertToLocalDate(endDate);

        long years = ChronoUnit.YEARS.between(start, end);
        long months = ChronoUnit.MONTHS.between(start, end);
        long days = ChronoUnit.DAYS.between(start, end);

        return Period.of((int)years, (int)months, (int)days);
    }

    /**
     * 取得给定日期的月份所含天数
     * @param date
     * @return
     */
    public static int getDaysInMonth(Date date) {
        LocalDate localDate = TimeConvertUtils.convertToLocalDate(date);
        return localDate.getMonth().length(localDate.isLeapYear());
    }

    /**
     * 取得给定日期的年份
     * @param date
     * @return
     */
    public static int getYear(Date date) {
        return TimeConvertUtils.convertToLocalDate(date).getYear();
    }

    /**
     * 取得给定日期的月份
     * @param date
     * @return
     */
    public static int getMonthOfYear(Date date) {
        return TimeConvertUtils.convertToLocalDate(date).getMonthValue();
    }

    /**
     * 取得给定日期的当月的多少日
     * @param date
     * @return
     */
    public static int getDayOfMonth(Date date) {
        return TimeConvertUtils.convertToLocalDate(date).getDayOfMonth();
    }

    /**
     * 取得当天的最后时间
     * @param date
     * @return
     */
    public static Date getLastTimeOfDay(Date date) {
        LocalDateTime localDateTime = TimeConvertUtils.convertToLocalDate(date).atTime(23, 59, 59);
        return TimeConvertUtils.convertToDate(localDateTime);
    }

    /**
     * 取得当月的最后一天
     * @param date
     * @return
     */
    public static Date getLashDayOfMonth(Date date) {
        LocalDate localDate = TimeConvertUtils.convertToLocalDate(date);
        int length = localDate.getMonth().length(localDate.isLeapYear());
        return TimeConvertUtils.convertToDate(localDate.withDayOfMonth(length));
    }
}
